﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Kaesoft.Hospedaje.Entities;
using Kaesoft.Hospedaje.Data;
using Microsoft.Practices.EnterpriseLibrary.ExceptionHandling;

namespace Kaesoft.Hospedaje.Business
{
    public partial class ReservacionBusiness
    {
        #region Metodos Publicos
        #region ObtenerCatalogos
        /// <summary>
        /// obtiene la lista de catalogos
        /// </summary>
        /// <param name="estructura">el id de estructura de catalogos</param>
        /// <returns>la lista consultada</returns>
        public List<Catalogo> ObtenerCatalogos(int estructura)
        {
            List<Catalogo> lista = null;
            try
            {
                using (ReservacionesEntities contexto = new ReservacionesEntities())
                {
                    lista = (from catalogos in contexto.Catalogoes
                             where !catalogos.borrado
                             && (catalogos.codigoEstructura == estructura || estructura == 0)
                             select catalogos).ToList();
                }

            }
            catch (Exception ex)
            {
                if (ExceptionPolicy.HandleException(ex, Constants.ExceptionPolicyDataAccess)) { throw; };
            }
            return lista;
        }
        #endregion

        #region ObtenerCatalogoSummary
        /// <summary>
        /// Obtener catálogos por tipo y con sus hijos
        /// </summary>
        /// <param name="tipoCatalogo">Tipo de catálogo</param>
        /// <returns>Colección de catálogos</returns>
        public List<CatalogoSummary> ObtenerCatalogoSummary(int tipoCatalogo)
        {
            List<CatalogoSummary> listaCatalogos = null;

            try
            {
                using (ReservacionesEntities ctx = new ReservacionesEntities())
                {
                    var todosCatalogos = (from catalogo in ctx.Catalogoes
                                          where !catalogo.borrado
                                          select catalogo).ToList();

                    var query = (from catalogo in ctx.Catalogoes
                                 where !catalogo.borrado
                                 && catalogo.codigoEstructura == tipoCatalogo
                                 select new
                                 {
                                     Codigo = catalogo.codigo,
                                     CodigoCadena = catalogo.codigoCadena,
                                     CodigoTipo = catalogo.codigoEstructura,
                                     CodigoPadre = catalogo.codigoPadre,
                                     CodigoTipoPadre = catalogo.codigoEstructuraPadre,
                                     Descripcion = catalogo.descripcion,
                                     Nombre = catalogo.nombre
                                 });

                    if (query.Count() > 0)
                    {
                        listaCatalogos = new List<CatalogoSummary>();
                        query.ToList().ForEach(catalogo =>
                        {
                            listaCatalogos.Add(new CatalogoSummary()
                            {
                                Codigo = catalogo.Codigo,
                                CodigoCadena = catalogo.CodigoCadena,
                                CodigoTipo = catalogo.CodigoTipo,
                                CodigoPadre = catalogo.CodigoPadre,
                                CodigoTipoPadre = catalogo.CodigoTipoPadre,
                                Descripcion = catalogo.Descripcion,
                                Nombre = catalogo.Nombre
                            });
                        });
                        BuscarCatalogosHijos(listaCatalogos, todosCatalogos);
                    }
                }
            }
            catch (Exception ex)
            {
                if (ExceptionPolicy.HandleException(ex, Constants.ExceptionPolicyDataAccess)) { throw; };
            }

            return listaCatalogos;
        }
        #endregion

        #region ObtenerCatalogoSummaryPorCriterio
        /// <summary>
        /// Obtener catálogos por criterios
        /// </summary>
        /// <param name="tipoCatalogo">Tipo de catálogo</param>
        /// <param name="tipoConsulta">Tipo de criterio de consulta</param>
        /// <param name="criterio">Criterio de consulta</param>
        /// <param name="indice">Indice de paginación</param>
        /// <returns>Lista paginada</returns>
        public PaginatedList<CatalogoSummary> ObtenerCatalogoSummaryPorCriterio(int tipoCatalogo, int tipoConsulta, string criterio, int indice)
        {
            int total = 0;
            List<CatalogoSummary> lista = new List<CatalogoSummary>();

            try
            {
                using (ReservacionesEntities ctx = new ReservacionesEntities())
                {
                    total = (from catalogo in ctx.Catalogoes
                             where !catalogo.borrado
                             && catalogo.codigoEstructura == tipoCatalogo
                             && ((catalogo.nombre.Contains(criterio) && tipoConsulta == (int)EnumBuscarCatalogo.Nombre)
                             || (catalogo.codigoCadena.StartsWith(criterio) && tipoConsulta == (int)EnumBuscarCatalogo.Codigo))
                             select catalogo).Count();

                    var listaCatalogos = (from catalogo in ctx.Catalogoes
                                          where !catalogo.borrado
                                          && catalogo.codigoEstructura == tipoCatalogo
                                          && ((catalogo.nombre.Contains(criterio) && tipoConsulta == (int)EnumBuscarCatalogo.Nombre)
                                          || (catalogo.codigoCadena.StartsWith(criterio) && tipoConsulta == (int)EnumBuscarCatalogo.Codigo))
                                          select catalogo).ToList().OrderBy(a => a.nombre).Skip(EntidadesUtil.PageSize * (indice)).Take(EntidadesUtil.PageSize).ToList(); ;

                    listaCatalogos.ToList().ForEach(catalogo =>
                        lista.Add(new CatalogoSummary()
                        {
                            Codigo = catalogo.codigo,
                            CodigoCadena = catalogo.codigoCadena,
                            CodigoTipo = catalogo.codigoEstructura,
                            CodigoPadre = catalogo.codigoPadre,
                            CodigoTipoPadre = catalogo.codigoEstructuraPadre,
                            Descripcion = catalogo.descripcion,
                            Nombre = catalogo.nombre
                        })
                    );

                }
            }
            catch (Exception ex)
            {
                if (ExceptionPolicy.HandleException(ex, Constants.ExceptionPolicyDataAccess)) { throw; };
            }

            return new PaginatedList<CatalogoSummary>(lista, total);
        }
        #endregion

        #region ObtenerParametrosSistema
        /// <summary>
        /// Obtener los parámetros del sistema
        /// </summary>
        /// <returns>Lista de parametros</returns>
        public List<Parametro> ObtenerParametrosSistema()
        {
            List<Parametro> listaParametros = null;

            try
            {
                using (ReservacionesEntities contexto = new ReservacionesEntities())
                {
                    listaParametros = (from parametro in contexto.Parametroes
                                       where !parametro.borrado
                                       select parametro).ToList();
                }
            }
            catch (Exception ex)
            {
                if (ExceptionPolicy.HandleException(ex, Constants.ExceptionPolicyDataAccess)) { throw; };
            }

            return listaParametros;
        }
        #endregion

        #region ObtenerUsuario
        /// <summary>
        /// Obtener los usuarios del sistema
        /// </summary>
        /// <returns> Obtener los usuarios del sistema</returns>
        public List<Usuario> ObtenerUsuarios()
        {
            List<Usuario> listaUsuario = null;

            try
            {
                using (ReservacionesEntities contexto = new ReservacionesEntities())
                {
                    listaUsuario = (from xUsuario in contexto.Usuarios
                                          where !xUsuario.borrado
                                          select xUsuario).ToList();
                }
            }
            catch (Exception ex)
            {
                if (ExceptionPolicy.HandleException(ex, Constants.ExceptionPolicyDataAccess)) { throw; };
            }

            return listaUsuario;
        }
        #endregion

        #region GrabarParametroSistema
        /// <summary>
        /// Grabar parametros del sistema
        /// </summary>
        /// <param name="parametros">Lista de parámetros</param>
        public void GrabarParametroSistema(List<Parametro> parametros)
        {
            Guid transactionToken = Guid.Empty;

            try
            {
                transactionToken = TransactionHelper.CreateTransaction();

                using (ReservacionesEntities ctx = new ReservacionesEntities())
                {
                    foreach (var parametro in parametros)
                    {
                        EntidadesUtil.SetCamposAuditoria(ctx, parametro, ServerCache.ObtenerDatosAuditoria(), false, false);
                        ctx.Parametroes.ApplyChanges(parametro);
                    }
                    ctx.SaveChanges();

                    TransactionHelper.CommitTransaction(ref transactionToken);
                }
            }
            catch (Exception ex)
            {
                if (ExceptionPolicy.HandleException(ex, Constants.ExceptionPolicyDataAccess)) { throw; };
            }
            finally
            {
                // si existe aun la transaccion, rollback
                if (Guid.Empty != transactionToken)
                {
                    TransactionHelper.RollbackTransaction(transactionToken);
                }
            }
        }
        #endregion

        #region GrabarTipoCatalogo
        /// <summary>
        /// Grabar tipos de catalogo
        /// </summary>
        /// <param name="parametros">Lista de tipos</param>
        public void GrabarTipoCatalogo(List<EstructuraCatalogo> tipos)
        {
            Guid transactionToken = Guid.Empty;

            try
            {
                transactionToken = TransactionHelper.CreateTransaction();

                using (ReservacionesEntities ctx = new ReservacionesEntities())
                {
                    foreach (var tipo in tipos)
                    {
                        EntidadesUtil.SetCamposAuditoria(ctx, tipo, ServerCache.ObtenerDatosAuditoria(), false, false);
                        ctx.EstructuraCatalogoes.ApplyChanges(tipo);
                    }
                    ctx.SaveChanges();

                    TransactionHelper.CommitTransaction(ref transactionToken);
                }
            }
            catch (Exception ex)
            {
                if (ExceptionPolicy.HandleException(ex, Constants.ExceptionPolicyDataAccess)) { throw; };
            }
            finally
            {
                // si existe aun la transaccion, rollback
                if (Guid.Empty != transactionToken)
                {
                    TransactionHelper.RollbackTransaction(transactionToken);
                }
            }
        }
        #endregion

        #region GrabarCatalogo
        /// <summary>
        /// Grabar catalogos
        /// </summary>
        /// <param name="parametros">Lista de catalogos</param>
        public void GrabarCatalogo(List<Catalogo> catalogos)
        {
            Guid transactionToken = Guid.Empty;

            try
            {
                transactionToken = TransactionHelper.CreateTransaction();

                using (ReservacionesEntities ctx = new ReservacionesEntities())
                {
                    foreach (var catalogo in catalogos)
                    {
                        EntidadesUtil.SetCamposAuditoria(ctx, catalogo, ServerCache.ObtenerDatosAuditoria(), false, false);
                        ctx.Catalogoes.ApplyChanges(catalogo);
                    }
                    ctx.SaveChanges();

                    TransactionHelper.CommitTransaction(ref transactionToken);
                }
            }
            catch (Exception ex)
            {
                if (ExceptionPolicy.HandleException(ex, Constants.ExceptionPolicyDataAccess)) { throw; };
            }
            finally
            {
                // si existe aun la transaccion, rollback
                if (Guid.Empty != transactionToken)
                {
                    TransactionHelper.RollbackTransaction(transactionToken);
                }
            }
        }
        #endregion

        #region ObtenerTipoCatalogos
        /// <summary>
        /// lista de tipos de catalogos
        /// </summary>
        /// <returns></returns>
        public List<EstructuraCatalogo> ObtenerTipoCatalogos()
        {
            List<EstructuraCatalogo> lista = null;
            try
            {
                using (ReservacionesEntities contexto = new ReservacionesEntities())
                {
                    lista = (from tipo in contexto.EstructuraCatalogoes
                             where !tipo.borrado
                             select tipo).ToList();
                }

            }
            catch (Exception ex)
            {
                if (ExceptionPolicy.HandleException(ex, Constants.ExceptionPolicyDataAccess)) { throw; };
            }
            return lista;
        }
        #endregion


        #endregion

        #region MétodosPrivados
        /// <summary>
        /// Buscar catálogos hijos a partir de un tipo de catálogo
        /// </summary>
        /// <param name="listaCatalogos">Lista filtrada de catalogos por tipo</param>
        /// <param name="todosCatalogos">Todos los catálogos</param>
        private void BuscarCatalogosHijos(IEnumerable<CatalogoSummary> listaCatalogos, List<Catalogo> todosCatalogos)
        {
            try
            {
                foreach (var catalogo in listaCatalogos)
                {
                    var query = (from generico in todosCatalogos
                                 where generico.codigoPadre == catalogo.Codigo
                                    && generico.codigoEstructuraPadre == catalogo.CodigoTipo
                                 select new
                                 {
                                     Codigo = generico.codigo,
                                     CodigoTipo = generico.codigoEstructura,
                                     CodigoTipoPadre = generico.codigoEstructuraPadre,
                                     Descripcion = generico.descripcion,
                                     Nombre = generico.nombre
                                 });

                    if (catalogo.CatalogoHijo == null)
                        catalogo.CatalogoHijo = new List<CatalogoSummary>();

                    if (query.Count() > 0)
                    {
                        query.ToList().ForEach(catHijo =>
                        {
                            catalogo.CatalogoHijo.Add(new CatalogoSummary()
                            {
                                Codigo = catHijo.Codigo,
                                CodigoTipo = catHijo.CodigoTipo,
                                CodigoTipoPadre = catHijo.CodigoTipoPadre,
                                Descripcion = catHijo.Descripcion,
                                Nombre = catHijo.Nombre
                            });
                        });

                        BuscarCatalogosHijos(catalogo.CatalogoHijo, todosCatalogos);
                    }
                }
            }
            catch (Exception ex)
            {
                if (ExceptionPolicy.HandleException(ex, Constants.ExceptionPolicyDataAccess)) { throw; };
            }
        }
        #endregion
    }
}